﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace GameBoardViewer.Board3D
{
    public class ModelParser
    {

        public static ModelDecl ParseModel(Model model)
        {
            ModelDecl decl = new ModelDecl();

            foreach (ModelMesh modelMesh in model.Meshes)
            {
                ModelMeshDecl mmD = new ModelMeshDecl();
                foreach (ModelMeshPart part in modelMesh.MeshParts)
                {
                    MeshPartDecl mpD = ParseMeshPart(part);
                    mmD.ModelMeshPart.Add(mpD);
                }

                decl.ModelMesh.Add(mmD);
            }

            return decl;
        }

        protected static MeshPartDecl ParseMeshPart(ModelMeshPart part)
        {
            MeshPartDecl decl = new MeshPartDecl();

            List<VertexElement> elem = part.VertexBuffer.VertexDeclaration.GetVertexElements().ToList();

            // convert vertexes
            //////////////////////////////////////////////////////////////////
            int stride = part.VertexBuffer.VertexDeclaration.VertexStride;
            byte[] vertexData = new byte[stride * part.NumVertices];
            part.VertexBuffer.GetData(part.VertexOffset * stride, vertexData, 0, part.NumVertices * stride, 1); // fixed 13/4/11

            Vector3 vertPosition = new Vector3();
            Vector2 vertTexture = new Vector2();
            for (int ndx = 0; ndx < vertexData.Length; ndx += stride)
            {
                vertPosition.X = BitConverter.ToSingle(vertexData, ndx);
                vertPosition.Y = BitConverter.ToSingle(vertexData, ndx + sizeof(float));
                vertPosition.Z = BitConverter.ToSingle(vertexData, ndx + sizeof(float) * 2);
                vertTexture.X = BitConverter.ToSingle(vertexData, ndx + sizeof(float) * 3 + sizeof(float) * 3);
                vertTexture.Y = BitConverter.ToSingle(vertexData, ndx + sizeof(float) * 3 + sizeof(float) * 3 + sizeof(float));

                VertexDecl declV = new VertexDecl();
                declV.Position = vertPosition;
                declV.Texture = vertTexture;
                decl.Vertexes.Add(declV);
            }

            // convert indexes
            /////////////////////////////////////////////////////////////////

            if (part.IndexBuffer.IndexElementSize != IndexElementSize.SixteenBits)
                throw new Exception(String.Format("Model uses 32-bit indices, which are not supported."));

            short[] s = new short[part.PrimitiveCount * 3];
            part.IndexBuffer.GetData<short>(part.StartIndex * 2, s, 0, part.PrimitiveCount * 3);
            for (int i = 0; i != part.PrimitiveCount; ++i)
            {
                IndexDecl idx = new IndexDecl();
                idx.Index1 = s[i * 3 + 0];
                idx.Index2 = s[i * 3 + 1];
                idx.Index3 = s[i * 3 + 2];
                decl.Indexes.Add(idx);
            }

            return decl;
        }
    }
}
